﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;

namespace HostTool.Core
{
    public class HostManage
    {
        public readonly string HostPath = Environment.SystemDirectory + @"\drivers\etc\hosts";
        public readonly string HostBackupPath = Environment.SystemDirectory + @"\drivers\etc\hosts_{0}.bak";
        private readonly FileOperate _fileOperate;


        public List<Host> CurrentHosts { private set; get; }

        public HostManage()
        {
            _fileOperate = new FileOperate(HostPath);
            CurrentHosts = ConversionHosts(GetHostContent()) ?? new List<Host>();
        }

        /// <summary>
        /// 获取hosts文件内容
        /// </summary>
        /// <returns></returns>
        public string GetHostContent()
        {
            return _fileOperate.Read();
        }

        /// <summary>
        /// 将Hosts文件转换实体
        /// </summary>
        /// <returns></returns>
        public List<Host> ConversionHosts(string content)
        {
            string[] strings = content.Split('\n');
            List<Host> hosts = new List<Host>();
            foreach (string s in strings)
            {
                var ip = s.GetIP().Trim();
                if (ip.IsNull()) continue;
                var domain = s.Replace(ip, "").Trim().Replace("\n", "").Replace("#", "").Trim();
                if (!ip.IsIP() || domain.IsNull() || !domain.IsDomain()) continue;
                Host host = new Host
                {
                    Domain = domain,
                    IP = ip,
                    Enable = s.IndexOf("#") == -1
                };
                var temphost = hosts.FirstOrDefault(h => h.Domain == host.Domain && h.IP == host.IP);
                if (temphost != null)
                {
                    if (!temphost.Enable && !host.Enable)
                    {
                        temphost.Enable = false;
                    }
                    else
                    {
                        temphost.Enable = true;
                    }
                }
                else
                {
                    hosts.Add(host);
                }
            }
            return hosts.OrderBy(h => h.Domain).ToList();
        }

        /// <summary>
        /// 当前Host对象转换文本
        /// </summary>
        /// <returns></returns>
        public string GetHostContent(List<Host> hosts)
        {
            StringBuilder content = new StringBuilder();
            const string template = "\r\n{0}{1}\t\t{2}";
            foreach (var host in hosts.OrderBy(h => h.Domain).ToList())
            {
                content.AppendFormat(template, !host.Enable ? "#" : "", host.IP, host.Domain);
            }
            return content.ToString();
        }

        /// <summary>
        /// 添加Host
        /// </summary>
        /// <param name="host"></param>
        public bool Add(Host host)
        {
            if (!Verify(host)) return false;
            CurrentHosts.Add(host);
            HostsWriterFile();
            CurrentHosts = ConversionHosts(GetHostContent()) ?? new List<Host>();
            return true;
        }

        /// <summary>
        /// 修改Host
        /// </summary>
        /// <param name="host"></param>
        public bool Update(Host host)
        {
            if (host.Enable)
            {
                var hosts = CurrentHosts.Where(h => h.Domain == host.Domain);
                foreach (Host item in hosts)
                {
                    item.Enable = false;
                }
            }
            CurrentHosts.First(h => h.Domain == host.Domain && h.IP == host.IP).Enable = host.Enable;
            HostsWriterFile();
            return true;
        }

        /// <summary>
        /// 验证是否存在同样的host
        /// </summary>
        /// <param name="host"></param>
        /// <returns></returns>
        public bool Verify(Host host)
        {
            if (host == null) return false;
            if (string.IsNullOrEmpty(host.IP) || !host.IP.IsIP()) return false;
            if (string.IsNullOrEmpty(host.Domain) || !host.Domain.IsDomain()) return false;
            var r = !CurrentHosts.Any(h => h.Domain == host.Domain && h.IP == host.IP);
            return r;
        }

        /// <summary>
        /// 删除Host
        /// </summary>        
        /// <param name="host"></param>
        public void DeleteHost(Host host)
        {
            CurrentHosts.Remove(CurrentHosts.First(h => h.IP == host.IP && h.Domain == host.Domain));
            HostsWriterFile();
            CurrentHosts = ConversionHosts(GetHostContent()) ?? new List<Host>();
        }

        /// <summary>
        /// 将对象转换文本，写入host
        /// </summary>
        public void HostsWriterFile()
        {
            _fileOperate.CreateText(GetHostContent(CurrentHosts));
        }

        /// <summary>
        /// hosts备份文件内容
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public string GetHostBackupContent(string path)
        {
            FileOperate fileOperate = new FileOperate(path);
            return fileOperate.Read();
        }

        /// <summary>
        /// 指定备份路径还原hosts文件
        /// </summary>
        /// <param name="path"></param>
        public void RestoreHost(string path)
        {
            _fileOperate.CreateText(GetHostBackupContent(path));
            CurrentHosts = ConversionHosts(GetHostContent()) ?? new List<Host>();
        }

        /// <summary>
        /// 指定备份路径(包含文件名称),备份hosts文件
        /// </summary>
        public void BackupHost(string path)
        {
            _fileOperate.Prototype.CopyTo(path, true);
        }

        public string DomainPing(string domain)
        {
            if (!domain.IsNull() && domain.IsDomain())
            {
                IPHostEntry nds = Dns.GetHostEntry(domain);
                if (nds.AddressList != null && nds.AddressList.Length > 0)
                {
                    return nds.AddressList[0].ToString();
                };
            }
            return "";
        }
    }

    public class Host
    {
        public string IP { get; set; }
        public string Domain { get; set; }
        public bool Enable { get; set; }
    }
}
